﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MSMQTriggerObjects;
using System.Collections;

namespace MSMQ.Triggers
{
	/// <summary>
	/// Manages a set of rules.
	/// </summary>
	public class RuleSet
		: IEnumerable<Rule>
	{
		#region Data Members

		/// <summary>
		/// The actual component that interacts with the MSMQ system.
		/// </summary>
		private MSMQRuleSet _internalRuleSet;

		/// <summary>
		/// The machine name the <see cref="RuleSet"/> operates with.
		/// </summary>
		private string _machineName;

		/// <summary>
		/// List of <see cref="Rule"/>s that this rule set has loaded.
		/// </summary>
		private List<Rule> _rules;

		#endregion

		#region Constructor(s)

		/// <summary>
		/// Creates a <see cref="RuleSet"/> which manages the local machine's MSMQ rules.
		/// </summary>
		public RuleSet()
			: this(Environment.MachineName)
		{
		}

		/// <summary>
		/// Creates a <see cref="RuleSet"/> which manages the specified machine's MSMQ rules.
		/// </summary>
		/// <param name="machineName">The name of the machine to connect with.</param>
		public RuleSet(string machineName)
		{
			_internalRuleSet = new MSMQRuleSetClass();
			_internalRuleSet.Init(machineName);
			_machineName = machineName;
			LoadAll();
		}

		#endregion

		#region Support Methods

		/// <summary>
		/// Loads all the rules available on the target machine.
		/// </summary>
		private void LoadAll()
		{
			_rules = new List<Rule>();
			for (int index = 0; index < _internalRuleSet.Count; index++)
			{
				_rules.Add(Load(index));
			}
		}

		/// <summary>
		/// Loads a rule at the given index.
		/// </summary>
		/// <param name="index">The index of the rule to load.</param>
		/// <returns><see cref="Rule"/> at the specified index.</returns>
		private Rule Load(int index)
		{
			string ruleId = null;
			string ruleName = null;
			string ruleDesc = null;
			string ruleCondition = null;
			string ruleAction = null;
			string ruleImplProgId = null;
			int ruleShowWindow = 0;

			_internalRuleSet.GetRuleDetailsByIndex(index,
				out ruleId, out ruleName, out ruleDesc, out ruleCondition, out ruleAction,
				out ruleImplProgId, out ruleShowWindow);
			Rule rule = new Rule();
			rule.Id = ruleId;
			rule.Name = ruleName;
			rule.Description = ruleDesc;
			rule.Condition = ruleCondition;
			rule.ExePath = ruleAction.Split(new char[] { '\t' })[1];
			rule.InteractsWithDesktop = ruleShowWindow == 1 ? true : false;
			return rule;
		}

		/// <summary>
		/// Update's the specified rule.
		/// </summary>
		/// <param name="rule">The rule to update.</param>
		public void Update(Rule rule)
		{
			_internalRuleSet.Refresh();
			_internalRuleSet.Update(
				rule.Id,
				rule.Name,
				rule.Description,
				rule.Condition,
				string.Format("EXE\t{0}", rule.ExePath),
				"MSMQTriggerObjects.MSMQRuleHandler",
				rule.InteractsWithDesktop ? 1 : 0);
		}

		#endregion

		#region IEnumerable<Rule> Members

		/// <summary>
		/// Gets the enumerator for the set.
		/// </summary>
		/// <returns>The enumerator for the rule set.</returns>
		public IEnumerator<Rule> GetEnumerator()
		{
			return _rules.GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		/// <summary>
		/// Gets the enumerator for the set.
		/// </summary>
		/// <returns>The enumerator for the rule set.</returns>
		IEnumerator IEnumerable.GetEnumerator()
		{
			return (IEnumerator)_rules.GetEnumerator();
		}

		#endregion
	}
}